package org.spring.springboot.app.mail.mailBind.service.impl;

import org.apache.commons.text.CharacterPredicates;
import org.apache.commons.text.RandomStringGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spring.springboot.app.base.Constants;
import org.spring.springboot.app.base.R;
import org.spring.springboot.app.base.Type;
import org.spring.springboot.app.user.sysuser.domain.vo.MailSendResVO;
import org.spring.springboot.app.mail.mailBind.domain.vo.MailSendBindVO;
import org.spring.springboot.app.mail.mailBind.domain.vo.ValidMailBindVO;
import org.spring.springboot.app.mail.mailBind.domain.vo.modifyMailBindingReqVO;
import org.spring.springboot.app.mail.mailBind.service.ISysuBindingService;
import org.spring.springboot.app.user.sysuser.dao.SysUserDao;
import org.spring.springboot.app.user.sysuser.domain.po.SysUserPO;
import org.spring.springboot.util.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
public class SysuBindingServiceImpl implements ISysuBindingService {

    private static final Logger LOGGER = LoggerFactory.getLogger(SysuBindingServiceImpl.class);

    @Autowired
    private SysUserDao sysUserDao;
    // key生成器,redis生成key必须用
    @Autowired
    private RedisUtils redisUtils;

    // 序列化对象redis处理方法
    @Autowired
    private RedisTemplate redisTemplate;
    @Value("${mail.transport.protocol}")
    private String protocol;
    @Value("${mail.smtp.host}")
    private String host;
    @Value("${mail.smtp.auth}")
    private String auth;
    @Value("${accout}")
    private String accout;
    @Value("${password}")
    private String password;
    /**
     * 邮箱发送方法
     * accout：发送人账号
     *password：发送人密码
     * mailtheme: 邮件主题
     * html:邮件内容(发送html)
     * Addressee：收件人
     */
    @Override
    public MimeMessage createEmail(final String accout,final String password, String mailtheme, String html, String Addressee) throws Exception {
        Properties config=new Properties();
        //验证邮件账号和秘密
        Session session= Session.getInstance(config, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(accout,password);
            }
        });
        //1创建邮件对
        MimeMessage mailMessage = new MimeMessage(session);
        //2设置发件人
        Address from=new InternetAddress(accout,"GAT","UTF-8");
        mailMessage.setFrom(from);
        //3设置收件人
        mailMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(Addressee));
        //4设置超送人
        //mailMessage.setRecipients(RecipientType.CC, new InternetAddress("121255@qq.com"));
        //5设置秘送人
        //mailMessage.setRecipients(RecipientType.BCC, new InternetAddress("121255@qq.com"));
        //6邮件发送主题
        mailMessage.setSubject(mailtheme,"UTF-8");


        mailMessage.setContent(html,"text/html; charset=utf-8");  //text/plain法文本
        //8设置邮件发送时间
        mailMessage.setSentDate(new Date());
        //确认设置完毕
        mailMessage.saveChanges();
        return mailMessage;
    }

    @Override
    public void mainEmail(String mailtheme, String html, String Addressee) throws Exception {

        MimeMessage mimeMessage=this.createEmail(accout,password,mailtheme,html,Addressee);
        Session session=mimeMessage.getSession();
        Properties config=session.getProperties();
        config.put("mail.transport.protocol",protocol);
        config.put("mail.smtp.host",host);
        //config.put("mail.smtp.port","25");
        config.put("mail.smtp.auth",auth);
        //config.put("mail.smtp.ssl.enable","false");
        Transport.send(mimeMessage);
    }


    @Override
    public int setBinding(String id,String email){
        SysUserPO po = new SysUserPO();
        po.setEmail(email);
        po.setId(id);
        po.preUpdate();
        return sysUserDao.updateByPrimaryKeySelective(po);
    }


    @Override
    public R modifyBinding(modifyMailBindingReqVO modifyMailBindingReqVO) {
        R r = new R();
        if (!r.valid(modifyMailBindingReqVO)) {
            return r;
        }
        SysUserPO po = sysUserDao.findByLoginId(modifyMailBindingReqVO.getLoginId());
        if (po == null) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("loginId", "账号不存在");
            return r;
        }
        String mailCode = redisUtils.getString(Constants.MAIL_SEND_CODE_REDIS_KEY + po.getId());
        if (mailCode == null) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("mailCode", "邮箱验证码已过期");
            return r;
        }
        if (!mailCode.equalsIgnoreCase(modifyMailBindingReqVO.getMailCode())) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("mailCode", "邮箱验证码不正确");
            return r;
        }
        SysUserPO user = new SysUserPO();
        user.setId(po.getId());
        user.setEmail(modifyMailBindingReqVO.getEmail());
        user.setUpdateBy(po.getId());
        user.setUpdateDate(new Date());
        int i = sysUserDao.updateByPrimaryKey(user);
        if (i == 0) {
            r.setType(Type.OperError);
            return r;
        }
        return r;
    }


    @Override
    public R<MailSendBindVO> sendMail(MailSendBindVO mailsendBindVO) {
        R<MailSendBindVO> r = new R<MailSendBindVO>();
        if (!r.valid(mailsendBindVO)) {
            return r;
        }

        if (redisUtils.hasStringKey(Constants.MAIL_SEND_OUT_TIME_REDIS_KEY + mailsendBindVO.getLoginId())) {  //mailsendBindVO.getLoginId()已改为id
            r.setType(Type.OperError);
            r.setMessage("验证码每60秒只能发送一次");
            return r;
        }

        String mailCode = redisUtils.getString(Constants.MAIL_SEND_IMAGE_CODE_REDIS_KEY + mailsendBindVO.getImageCaptchaToken());
        if (mailCode == null) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("imageCode", "图片验证码已过期,请点击图片验证码刷新");
            return r;
        }
        if (!mailCode.equalsIgnoreCase(mailsendBindVO.getImageCode())) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("imageCode", "图片验证码不正确");
            return r;
        }

        String code = new RandomStringGenerator.Builder().withinRange('0', 'Z').filteredBy(CharacterPredicates.DIGITS, CharacterPredicates.LETTERS).build().generate(4);
        String html = "你的GTA后台管理系统的替换新邮箱验证码为:<span style=\"color:red;\">" + code + "</span>,如果这不是你本人的操作,请忽略此条邮件";
        try {
            this.mainEmail("GTA后台管理系邮箱替换", html, mailsendBindVO.getEmail());
        } catch (Exception e) {
            r.setType(Type.OperError);
            r.setMessage("发送邮件失败,请稍后在试或者联系客服");
          //  log.error(e);
            return r;
        }
        redisUtils.setString(Constants.MAIL_SEND_OUT_TIME_REDIS_KEY + mailsendBindVO.getLoginId(), new Date().getTime() + "", 60, TimeUnit.SECONDS);
        redisUtils.setString(Constants.MAIL_SEND_CODE_REDIS_KEY + mailsendBindVO.getLoginId(), code, 10 * 60, TimeUnit.SECONDS);
       /* MailSendResVO vo = new MailSendResVO();
        vo.setEmail(po.getEmail());*/
        return r;
    }

    @Override
    public R<MailSendResVO> validMailCode(ValidMailBindVO vo) {
        R<MailSendResVO> r = new R<MailSendResVO>();
        if (!r.valid(vo)) {
            return r;
        }
       /* SysUserPO po = sysUserDao.findByLoginId(vo.getLoginId());
        if (po == null) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("loginId", "账号不存在");
            return r;
        }*/
        if (vo.getEmail() == null || vo.getEmail().length() == 0) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("loginId", "邮箱为空！");
            return r;
        }
        String mailCode = redisUtils.getString(Constants.MAIL_SEND_CODE_REDIS_KEY + vo.getLoginId());
        if (mailCode == null) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("mailCode","邮箱验证码已过期,请重新发送");
            return r;
        }
        if (!mailCode.equalsIgnoreCase(vo.getMailCode())) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("mailCode","邮箱验证码错误");
            return r;
        }
        ValidMailBindVO validMailBindVO = new ValidMailBindVO();
        validMailBindVO.setEmail(vo.getEmail());
        this.setBinding(vo.getLoginId(),vo.getEmail());
        return r;
    }
}
